Functional Testing
==================

Before reading this section, it is recommended that you read the [Selenium documentation](http://seleniumhq.org/docs/) and the [PHPUnit documentation](http://www.phpunit.de/wiki/Documentation) first. We summarize in the following the basic principles of writing a functional test in Yii:

 * Like unit test, a functional test is written in terms of a class `XyzTest` which extends from [CWebTestCase], where `Xyz` stands for the class being tested. Because `PHPUnit_Extensions_SeleniumTestCase` is the ancestor class for [CWebTestCase], we can use all methods inherited from this class.

 * The functional test class is saved in a PHP file named as `XyzTest.php`. By convention, the functional test file may be stored under the directory `protected/tests/functional`.

 * The test class mainly contains a set of test methods named as `testAbc`, where `Abc` is often the name of a feature to be tested. For example, to test the user login feature, we can have a test method named as `testLogin`.

 * A test method usually contains a sequence of statements that would issue commands to Selenium RC to interact with the Web application being tested. It also contains assertion statements to verify that the Web application responds as expected.

Before we describe how to write a functional test, let's take a look at the `WebTestCase.php` file generated by the `yiic webapp` command. This file defines `WebTestCase` that may serve as the base class for all functional test classes.

~~~
[php]
define('TEST_BASE_URL','http://localhost/yii/demos/blog/index-test.php/');

class WebTestCase extends CWebTestCase
{
	/**
	 * Sets up before each test method runs.
	 * This mainly sets the base URL for the test application.
	 */
	protected function setUp()
	{
		parent::setUp();
		$this->setBrowserUrl(TEST_BASE_URL);
	}

	......
}
~~~

The class `WebTestCase` mainly sets the base URL of the pages to be tested. Later in test methods, we can use relative URLs to specify which pages to be tested.

We should also pay attention that in the base test URL, we use `index-test.php` as the entry script instead of `index.php`. The only difference between `index-test.php` and `index.php` is that the former uses `test.php` as the application configuration file while the latter `main.php`.

We now describe how to test the feature about showing a post in the [blog demo](http://www.yiiframework.com/demos/blog). We first write the test class as follows, noting that the test class extends from the base class we just described:

~~~
[php]
class PostTest extends WebTestCase
{
	public $fixtures=array(
		'posts'=>'Post',
	);

	public function testShow()
	{
		$this->open('post/1');
	    // verify the sample post title exists
	    $this->assertTextPresent($this->posts['sample1']['title']);
	    // verify comment form exists
	    $this->assertTextPresent('Leave a Comment');
	}

	......
}
~~~

Like writing a unit test class, we declare the fixtures to be used by this test. Here we indicate that the `Post` fixture should be used. In the `testShow` test method, we first instruct Selenium RC to open the URL `post/1`. Note that this is a relative URL, and the complete URL is formed by appending it to the base URL we set in the base class (i.e. `http://localhost/yii/demos/blog/index-test.php/post/1`). We then verify that we can find the title of the `sample1` post can be found in the current Web page. And we also verify that the page contains the text `Leave a Comment`.

> Tip: Before running functional tests, the Selenium-RC server must be started. This can be done by executing the command `java -jar selenium-server.jar` under your Selenium server installation directory.

